#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <csi_config.h>
#include <drv_mailbox.h>
#include <assert.h>
#include <ulog/ulog.h>
#include <aos/kernel.h>
#include "soc.h"
#include "pin.h"
#include "ipcm.h"

#define TAG "IPCM"

typedef struct _msg_pkg_t {
    unsigned int cmd;
    unsigned int value;
	void 		*pData;
} msg_pkg_t;

#define IPC_QUEUE_SIZE    (100)
#define IPC_QUEUE_MAX_MSG_SIZE (sizeof(msg_pkg_t))

static struct message_msg mb_msg;
static struct message_msg inmsg;
static struct message_msg outmsg;
static uint8_t msg_data[32] = {0};
static uint8_t outData[32] = {0};
static int inData[32] = {0};
static aos_queue_t g_ipc_queue;
static char g_ipc_msg[IPC_QUEUE_SIZE*2 * IPC_QUEUE_MAX_MSG_SIZE];
static mailbox_handle_t mailbox_handle;
static volatile uint8_t s_event_done;
static ipcm_funclist_t *g_ipcm_funclist;

static int post_queue_msg(aos_queue_t *queue, msg_pkg_t *msg)
{
    int ret;
    ret = aos_queue_send(queue, (void *)msg, sizeof(msg_pkg_t));
    if (ret) {		
		LOGE(TAG,"%s(%d) ret=%d\r\n", __FUNCTION__, __LINE__, ret);
        return -1;
    }
    return 0;
}


static void mailbox_event_cb_fun(mailbox_event_e event, uint8_t *data, uint32_t len)
{
    if (event == MAILBOX_EVENT_SEND_COMPLETE) {
        //printf("[CB]:send done\n");
    } else {
    	s_event_done = 1;
    	//ringQueue_put(pRQ, data, sizeof(struct message_msg ));
		//int ret;
		msg_pkg_t msg;
		msg.cmd = 0;
		msg.pData = data;
		//printf("mailbox irq \n");
		post_queue_msg(&g_ipc_queue, &msg);
    }
}



int IPCM_init(ipcm_funclist_t *funclist)
{
    if(funclist == NULL)
    {
        LOGE(TAG, "%s(%d): BAD param!!!\r\n", __FUNCTION__, __LINE__);
        return -1;
    }
    g_ipcm_funclist = funclist;

	int ret = aos_queue_new(&g_ipc_queue, (void *)&g_ipc_msg, IPC_QUEUE_SIZE * IPC_QUEUE_MAX_MSG_SIZE, IPC_QUEUE_MAX_MSG_SIZE);
	if (ret){
		LOGE(TAG, "%s(%d) ret=%d\r\n", __FUNCTION__, __LINE__, ret);
		assert(0);
        return; 
    }

	mailbox_handle = drv_mailbox_initialize(EXAMPLE_MAILBOX_IDX, mailbox_event_cb_fun);
	if (mailbox_handle == NULL) {
		printf(" drv_mailbox_initialize failed\n");
		return -1;
	}
}


static int IPCM_ExeById(uint32_t id)
{
	int i = 0;
	int ret = -1;

	for(i = 0;i < g_ipcm_funclist->num; i++)
	{
		if(id == g_ipcm_funclist->funclist[i].id)
		{
             printf("i=%d; %p\n", i, g_ipcm_funclist->funclist[i].exe);
			return i;
		}
	}

	return ret;
}


int IPCM_run()
{
    char data[256];
    uint32_t  size = 0;
    int ret = aos_queue_recv(&g_ipc_queue, AOS_WAIT_FOREVER, (void *)data, (unsigned int *)(&size));
    if ((ret != 0) || (size == 0)){			
        LOGD(TAG, "recv cmd none \n");
        return 0;
    }

    msg_pkg_t *msg = (msg_pkg_t *)data;
    struct message_msg *temp_msg = (struct message_msg *)(msg->pData);
    printf("cmd=%d\n", temp_msg->command);
    ret = IPCM_ExeById(temp_msg->command);
    if(ret >= 0) {
        g_ipcm_funclist->funclist[ret].exe(temp_msg);
    }

//		printf("ipc back flag %d \n",outmsg.flag);
//		printf("ipc id %d \n",outmsg.id);
//		printf("ipc sem %p \n",outmsg.sem);

    if(temp_msg->flag == 1)
    {
        temp_msg->flag = MESSAGE_ACK;
        ret = drv_mailbox_send_mail(mailbox_handle, temp_msg, sizeof(struct message_msg));
        if (ret < 0) {
            printf(" mailbox send failed\n");
        }
    }

}


int IPCM_final()
{
    return 0;
}



void printIpcmData(ipcm_data_t * ipc_data)
{
	LOGD(TAG, "_ipcData @ %p\n",ipc_data);
	LOGD(TAG, "in  @ %p\n",ipc_data->in);
	LOGD(TAG, "out @ %p\n",ipc_data->out);
}

